/************************************************************
 * Project Name         [Thinking_In_Java]
 * File Name            [Example_10_User_Defined_Layout.java]
 * Creation Date        [23-Jun-2014]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ************************************************************/
package pkg_05_swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.LayoutManager;

import javax.swing.JButton;
import javax.swing.JFrame;

/**
 * 自定义布局管理器
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
public class Example_10_User_Defined_Layout {

	/**
	 * 测试方法
	 * 
	 * @param args
	 *            命令行参数
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				CircleLayoutFrame frame = new CircleLayoutFrame();
				frame.setVisible(true);
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			}
		});
	}
}

/**
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 */
class CircleLayoutFrame extends JFrame {

	private static final long serialVersionUID = 1768177381905983615L;

	/**
	 * 构造方法
	 */
	public CircleLayoutFrame() {
		setTitle("User-defined Layout");
		setLayout(new CircleLayout());
		this.add(new JButton("Yellow"));
		this.add(new JButton("Blue"));
		this.add(new JButton("Red"));
		this.add(new JButton("Green"));
		this.add(new JButton("Orange"));
		this.add(new JButton("Fuchsia"));
		this.add(new JButton("Indigo"));
		pack();
	}
}

/**
 * 自定义的Layout
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 */
class CircleLayout implements LayoutManager {

	private int minWidth = 0;
	private int minHeight = 0;
	private int preferredWidth = 0;
	private int preferredHeight = 0;
	private int maxComponentWidth = 0;
	private int maxComponentHeight = 0;

	private boolean sizeSet = false;

	public void setSizes(Container parent) {
		if (sizeSet)
			return;
		// 获得容器所包含的组件数
		int n = parent.getComponentCount();

		minWidth = 0;
		minHeight = 0;
		preferredWidth = 0;
		preferredHeight = 0;
		maxComponentWidth = 0;
		maxComponentHeight = 0;

		for (int i = 0; i < n; i++) {
			Component component = parent.getComponent(i);
			if (component.isVisible()) {
				Dimension dim = component.getPreferredSize();
				maxComponentWidth = Math.max(maxComponentWidth, dim.width);
				maxComponentHeight = Math.max(maxComponentHeight, dim.height);

				preferredWidth += dim.width;
				preferredHeight += dim.height;
			}
			minWidth = preferredWidth / 2;
			minHeight = preferredHeight / 2;
			sizeSet = true;
		}
	}

	@Override
	public void addLayoutComponent(String name, Component comp) {
		// not called
	}

	@Override
	public void removeLayoutComponent(Component comp) {
		// not called
	}

	/**
	 * 返回本布局下容器的最小尺寸
	 * 
	 * @param parent
	 * @return 最小尺寸
	 */
	@Override
	public Dimension minimumLayoutSize(Container parent) {
		setSizes(parent);
		// 计算容器的边界
		Insets insets = parent.getInsets();
		int width = minWidth + insets.left + insets.right;
		int height = minHeight + insets.top + insets.bottom;
		return new Dimension(width, height);
	}

	/**
	 * 返回本布局下容器的首选尺寸
	 * 
	 * @param parent
	 * @return 首选尺寸
	 */
	@Override
	public Dimension preferredLayoutSize(Container parent) {
		setSizes(parent);
		// 计算容器的边界
		Insets insets = parent.getInsets();
		int width = preferredWidth + insets.left + insets.left;
		int height = preferredHeight + insets.top + insets.bottom;
		return new Dimension(width, height);
	}

	/**
	 * 布局的容器
	 * 
	 * @param parent
	 */
	@Override
	public void layoutContainer(Container parent) {
		setSizes(parent);
		// 计算圆心
		Insets insets = parent.getInsets();
		int containerWidth = parent.getSize().width - insets.left
				- insets.right;
		int containerHeight = parent.getSize().height - insets.top
				- insets.bottom;
		int centerX = insets.left + containerWidth / 2;
		int centerY = insets.top + containerHeight / 2;

		// 计算半径
		int radiusX = (containerWidth - maxComponentWidth) / 2;
		int radiusY = (containerHeight - maxComponentHeight) / 2;

		int radius = Math.min(radiusX, radiusY);

		int n = parent.getComponentCount();
		for (int i = 0; i < n; i++) {
			Component component = parent.getComponent(i);
			if (component.isVisible()) {
				double angle = 2 * Math.PI * i / n;
				// 组件的中心点
				int x = centerX + (int) (Math.cos(angle) * radius);
				int y = centerY + (int) (Math.sin(angle) * radius);

				Dimension dim = component.getPreferredSize();
				component.setBounds(x - dim.width / 2, y - dim.height / 2,
						dim.width, dim.height);
			}
		}
	}

}